const colors = require('colors')
const {env} = require('process')
class Strategy {
    constructor() { }

    busRd(host) { }

    busRdX(host) { }

    flush(host){
        if (env.lang === 'en') 
            console.log(`${host.processor} 's ${host.id} has been write back to ram ${host.content}`)
        if (env.lang === 'zh') 
            console.log(`${host.processor} 号处理器的 ${host.id} 号缓存块被写回内存 ${host.content}`)
    }
}

class Snooper extends Strategy {
    constructor() {
        super()
        this.cacheBlocks = new Set()
    }

    addSnooper(cacheBlock) {
        this.cacheBlocks.add(cacheBlock)
    }

    deleteSnooper(cacheBlock) {
        this.cacheBlocks.delete(cacheBlock)
    }


    busRd(host) {
        console.log(colors.bgGreen(colors.black('总线发出读信号')))
        this.addSnooper(host)
        for (let cb of this.cacheBlocks) {
            if (cb.processor !== host.processor && cb.content === host.content) cb.busRd()
        }
    }

    busRdX(host) {
        console.log(colors.bgGreen(colors.black('总线发出写信号')))
        this.addSnooper(host)
        for (let cb of this.cacheBlocks) {
            if (cb.processor !== host.processor && cb.content === host.content) cb.busRdX()
        }
    }

    flush(host){
        super.flush(host)
    }
}

class Directory extends Strategy{
    constructor(processor,cacheSize){
        super()
        this.ram = Array(processor * cacheSize * 2).fill(0).map(()=> new Set())
    }

    busRd(host) {
        console.log(colors.bgGreen(colors.black(`向宿主节点发送读不命中(${host.processor},${host.content})消息`)))
        for (let cb of this.ram[host.content]) {
            if(cb.currentState.__proto__.constructor.name == 'Shared')continue
            console.log(colors.bgGreen(colors.black(`向远程节点 ${cb.processor} 发送取数据块 ${host.content} 的消息`)))
            cb.busRd()
        }
        console.log(colors.bgGreen(colors.black(`把数据块送给节点${host.processor}`)))
        for(let r of this.ram){
            if(r.has(host))r.delete(host)
        }
        this.ram[host.content].add(host)
        console.log(colors.bgGreen(colors.black(`共享节点为${[...this.ram[host.content]].map(x => x.processor)}`)))
    }

    busRdX(host) {
        console.log(colors.bgGreen(colors.black(`向宿主节点发送写(${host.processor},${host.content})消息`)))
        for (let cb of this.ram[host.content]) {
            console.log(colors.bgGreen(colors.black(`向远程节点 ${cb.processor} 发送数据块 ${host.content} 失效的消息`)))
            for(let r of this.ram){
                if(r.has(cb))r.delete(cb)
            }
            cb.busRdX()
        }
        for(let r of this.ram){
            if(r.has(host))r.delete(host)
        }
        console.log(colors.bgGreen(colors.black(`把数据块送给节点${host.processor}`)))
        this.ram[host.content].add(host)
        console.log(colors.bgGreen(colors.black(`独占节点为${[...this.ram[host.content]].map(x => x.processor)}`)))
    }

    flush(host){
        super.flush(host)
    }
}


module.exports.Snooper = Snooper
module.exports.Strategy = Strategy
module.exports.Directory = Directory